<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Tetris</title>
	
	<style>
	
		#Tetris{
			display:inline-block;
			border:solid 2px blue;
		}
		
		#preview{
			display:inline-block;
			border:solid 2px blue;
		}
		
		.container{
			margin:0 auto;
			max-width:600px;
		}
		
	</style>
	
</head>
<body>
	<div class="container">
		<canvas id="Tetris"></canvas>
		<canvas id="preview"></canvas>
	</div>

	
	<script>
	
		var tBlock=
					[
						[
									[
										[1,1,1],
										[0,1,0]
									],
									[
										[0,1],
										[1,1],
										[0,1]
									],
									[
										[0,1,0],
										[1,1,1],
									],
									[
										[1,0],
										[1,1],
										[1,0]
									],				

						],//T
						[
									[
										[1],
										[1],
										[1],
										[1]
									],
									[
										[1,1,1,1]
									]			

						],//I
						[
									[
										[1,1],
										[1,1],
									]		

						],//O
						[
									[
										[0,1,1],
										[1,1,0]
									],	
									[
										[1,0],
										[1,1],
										[0,1]
									],					

						],//S
						[
									[
										[1,1,0],
										[0,1,1]
									],	
									[
										[0,1],
										[1,1],
										[1,0]
									]				

						],//Z
						[
									[
										[0,1],
										[0,1],
										[1,1]
									],	
									[
										[1,0,0],
										[1,1,1],
									],					
									[
										[1,1],
										[1,0],
										[1,0]
									],	
									[
										[1,1,1],
										[0,0,1],
									]				
						],//J
						[
									[
										[1,0],
										[1,0],
										[1,1]
									],	
									[
										[1,1,1],
										[1,0,0],
									],					
									[
										[1,1],
										[0,1],
										[0,1]
									],
									[
										[0,0,1],
										[1,1,1],
									]			
						]//L
					];		
						
		var activeBlock=null;
		var previewBlock=null;
		
		var EDGE=20;
		var BOARD_WIDTH=20;
		var BOARD_HEIGHT=31;
		
		var board=new Array(31);
		
		//绘制当前活动方块
		function paintActiveBlock(context){
			for(var i=0;i<activeBlock.shape.length;i++){
				for(var j=0;j<activeBlock.shape[i].length;j++){
					if(activeBlock.shape[i][j]==1){
					
						var boardX=activeBlock.x+j;
						var boardY=activeBlock.y+i;
						
						paintBlock(boardX*EDGE,boardY*EDGE,context);
					}
				}
			}
		}
		
		//初始化面板
		function initBoard(){
			for(var i=0;i<board.length;i++){
			   board[i]=new Array(20);
			}
			
			for(var i=0;i<board.length;i++){
			   for(var j=0;j<board[i].length;j++){
			       board[i][j]=0;
			   }
			}
			
		}
		
		//绘制俄罗斯方块面板
		function paintBoard(context){
			for(var i=0;i<board.length;i++){
			    for(var j=0;j<board[i].length;j++){
				    if(board[i][j]==1){
						paintBlock(j*EDGE,i*EDGE,context);
					}
				}
			}
		}
					
		//绘制小方块
		function paintBlock(x,y,context){
			context.beginPath();
			context.strokeStyle="blue";
			context.lineWidth=2;			
			context.strokeRect(x,y,EDGE,EDGE);
			context.closePath();
		}
		

		function clearBlock(context){
			context.clearRect(0,0,context.canvas.width,context.canvas.height);
		}
		
		//更新活动情况
		function rePaint(context){
		
			clearBlock(context);
			
			clearBlock(previewContext);
			
			paintActiveBlock(context);
			
			paintPreviewBlock(previewContext);
			
			paintBoard(context);
		}
		
		function isValidLeft(){
	        
			//判断向左移动是否越过边界
			var testX=activeBlock.x-1;

			if(testX<0){
				return false;
			}
			
			if(isTouchLeftBlock()){
			    return false;
			}
			
			return true;
        }
		
		function isTouchLeftBlock(){
		    for(var i=0;i<activeBlock.shape.length;i++){
				for(var j=0;j<activeBlock.shape[i].length;j++){
				    if(activeBlock.shape[i][j]==1){
					
					    var testX=activeBlock.x+j-1;
						var testY=activeBlock.y+i;
						if(board[testY][testX]==1){
						    return true;
						}
					}
				}
			}
			
			return false;
		}

		function moveLeft(){

			if(isValidLeft()){
				activeBlock.x-=1;
			}
			
		}

		function isValidChangeStyle(){
            if(isOutBoundary()||isTouchBlock()){	
			    return false;
			}
             return true;
        }
        
        function isOutBoundary(){
			var sum=tBlock[activeBlock.category].length;
			var index=(1+activeBlock.index)%sum;

            var width=board[0].length-1;
            var height=board.length-1;      
			
            var testBlock=tBlock[activeBlock.category][index];
            for(var i=0;i<testBlock.length;i++){
                for(var j=0;j<testBlock[i].length;j++){
                    if(testBlock[i][j]==1){
                        var testX=activeBlock.x+j;
                        var testY=activeBlock.y+i;
                        if(testX<0||testX>width||testY<0||testY>height){
                            return true;
                        }
                    }
                }
            }
            return false;         
        }

        function isTouchBlock(){
			var sum=tBlock[activeBlock.category].length;
			var index=(1+activeBlock.index)%sum;

            var width=board[0].length-1;
            var height=board.length-1;      
			
            var testBlock=tBlock[activeBlock.category][index];
            for(var i=0;i<testBlock.length;i++){
                for(var j=0;j<testBlock[i].length;j++){
                    if(testBlock[i][j]==1){
                        var testX=activeBlock.x+j;
                        var testY=activeBlock.y+i;
                        if(board[testY][testX]==1){
                            return true;
                        }
                    }
                }
            }

            return false;                        
        }		

		function changeStyle(){
            if(isValidChangeStyle()){

				var sum=tBlock[activeBlock.category].length;
				var index=(1+activeBlock.index)%sum;

				activeBlock.shape=tBlock[activeBlock.category][index];
				activeBlock.index=index                
            }
		}

		function isValidRight(){

			var testX=activeBlock.x+activeBlock.shape[0].length+1;

			if(testX>BOARD_WIDTH){
				return false;
			}
			
			if(isTouchRightBlock()){
				return false;
			}
			
			return true;
        }
		
		function isTouchRightBlock(){
		    for(var i=0;i<activeBlock.shape.length;i++){
				for(var j=0;j<activeBlock.shape[i].length;j++){
				    if(activeBlock.shape[i][j]==1){
					
					    var testX=activeBlock.x+j+1;
						var testY=activeBlock.y+i;
						if(board[testY][testX]==1){
						    return true;
						}
					}
				}
			}
			
			return false;
		}		
		
		function moveRight(){
			if(isValidRight()){
				activeBlock.x+=1;
			}
		}
		
		function isValidDown(){
		
			if(isOutOfBoundary()||touchOtherBlock()){
				return false;
			}
			
			return true;
		}
		
		function isOutOfBoundary(){
		
			var testY=activeBlock.y+activeBlock.shape.length+1;
			if(testY>BOARD_HEIGHT){
			    return true;
			}	
			return false;
		}
		
		//冲突检测
		function touchOtherBlock(){
			for(var i=0;i<activeBlock.shape.length;i++){	
				for(var j=0;j<activeBlock.shape[i].length;j++){
					if(activeBlock.shape[i][j]==1){
					
						var testX=activeBlock.x+j;
					    var testY=activeBlock.y+i+1;
						
						if(board[testY][testX]==1){
							return true;
						}
							
					}
				}
			}
			
			return false;
		}
        
        function putInBoard(){
            for(var i=0;i<activeBlock.shape.length;i++){
                for(var j=0;j<activeBlock.shape[i].length;j++){
                    if(activeBlock.shape[i][j]==1){
                         board[i+activeBlock.y][j+activeBlock.x]=1;
                    } 
                }
            } 
        }

		function cleanLine(num){
			if(isAllFull(num)){
                for(var i=num-1;i>=0;i--){
                    board[i+1]=board[i];
                } 

                fillLineZero(0);
            }
		}
		
        function fillLineZero(num){
            for(var i=0;i<board[0].length;i++){
                board[num][i]=0; 
            }
        }

		function isAllFull(num){
			for(var i=0;i<board[0].length;i++){
				if(board[num][i]==0){
                    return false;
				}
			}
            return true;
		}

        function cleanLines(){
            for(var i=activeBlock.y;i<activeBlock.y+activeBlock.shape.length;i++){
                cleanLine(i);
            }
        }

		function moveDown(){
			if(isValidDown()){
				activeBlock.y=activeBlock.y+1;
			}else{
				putInBoard();
                cleanLines();
				
				activeBlock=previewBlock;
				previewBlock=makeNewTerisBlock();
			}
		}		
		
		function makeNewTerisBlock(){
			var randomNum=Math.floor(Math.random()*7);
			
			var tempX=Math.floor((board[0].length-tBlock[randomNum][0][0].length)/2);
			return {x:tempX,y:0,shape:tBlock[randomNum][0],category:randomNum,index:0};
		}
		
		function paintPreviewBlock(context){
		
		     var x=Math.floor((6-previewBlock.shape[0].length)/2)*EDGE;
			 var y=Math.floor((6-previewBlock.shape.length)/2)*EDGE;
			 
			 for(var i=0;i<previewBlock.shape.length;i++){
				for(var j=0;j<previewBlock.shape[i].length;j++){
					if(previewBlock.shape[i][j]==1){
					     paintBlock(x+j*EDGE,y+i*EDGE,context);
					}
				}
			 }
		}
		
		//-----------------------------------------main----
		//创建绘画背景
		var tetris=document.getElementById("Tetris");
		var preview=document.getElementById("preview");
		
		var context=tetris.getContext("2d");
		var previewContext=preview.getContext("2d");
		
		context.canvas.height=620;
		context.canvas.width=400;
		
		previewContext.canvas.height=120;
		previewContext.canvas.width=120;		
		
		initBoard();
		
		activeBlock=makeNewTerisBlock();
		previewBlock=makeNewTerisBlock();
		
		setInterval(function(){rePaint(context);},100);
		
		setInterval(function(){moveDown();},600);
		
		//键盘控制
		document.onkeydown=function keyControl(event){
			var event = event || window.event;
			switch (event.keyCode){
				case 37: moveLeft();break;
				case 38: changeStyle();break;
				case 39: moveRight();break;
				case 40: moveDown();break;
			}
		}
		//-------------------------------------------------
	</script>
</body>
</html>